﻿using System;
using System.IO;
using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;

namespace Mono.Cecil.PE
{
	// Token: 0x020000F0 RID: 240
	internal sealed class Image : IDisposable
	{
		// Token: 0x060009A8 RID: 2472 RVA: 0x000057FB File Offset: 0x000039FB
		public Image()
		{
			this.counter = new Func<Table, int>(this.GetTableLength);
		}

		// Token: 0x060009A9 RID: 2473 RVA: 0x0002AE28 File Offset: 0x00029028
		public bool HasTable(Table table)
		{
			return this.GetTableLength(table) > 0;
		}

		// Token: 0x060009AA RID: 2474 RVA: 0x0002AE44 File Offset: 0x00029044
		public int GetTableLength(Table table)
		{
			return (int)this.TableHeap[table].Length;
		}

		// Token: 0x060009AB RID: 2475 RVA: 0x0002AE68 File Offset: 0x00029068
		public int GetTableIndexSize(Table table)
		{
			return (this.GetTableLength(table) < 65536) ? 2 : 4;
		}

		// Token: 0x060009AC RID: 2476 RVA: 0x0002AE8C File Offset: 0x0002908C
		public int GetCodedIndexSize(CodedIndex coded_index)
		{
			int num = this.coded_index_sizes[(int)coded_index];
			bool flag = num != 0;
			int result;
			if (flag)
			{
				result = num;
			}
			else
			{
				result = (this.coded_index_sizes[(int)coded_index] = coded_index.GetSize(this.counter));
			}
			return result;
		}

		// Token: 0x060009AD RID: 2477 RVA: 0x0002AED0 File Offset: 0x000290D0
		public uint ResolveVirtualAddress(uint rva)
		{
			Section sectionAtVirtualAddress = this.GetSectionAtVirtualAddress(rva);
			bool flag = sectionAtVirtualAddress == null;
			if (flag)
			{
				throw new ArgumentOutOfRangeException();
			}
			return this.ResolveVirtualAddressInSection(rva, sectionAtVirtualAddress);
		}

		// Token: 0x060009AE RID: 2478 RVA: 0x0002AF00 File Offset: 0x00029100
		public uint ResolveVirtualAddressInSection(uint rva, Section section)
		{
			return rva + section.PointerToRawData - section.VirtualAddress;
		}

		// Token: 0x060009AF RID: 2479 RVA: 0x0002AF24 File Offset: 0x00029124
		public Section GetSection(string name)
		{
			foreach (Section section in this.Sections)
			{
				bool flag = section.Name == name;
				if (flag)
				{
					return section;
				}
			}
			return null;
		}

		// Token: 0x060009B0 RID: 2480 RVA: 0x0002AF70 File Offset: 0x00029170
		public Section GetSectionAtVirtualAddress(uint rva)
		{
			foreach (Section section in this.Sections)
			{
				bool flag = rva >= section.VirtualAddress && rva < section.VirtualAddress + section.SizeOfRawData;
				if (flag)
				{
					return section;
				}
			}
			return null;
		}

		// Token: 0x060009B1 RID: 2481 RVA: 0x0002AFCC File Offset: 0x000291CC
		private BinaryStreamReader GetReaderAt(uint rva)
		{
			Section sectionAtVirtualAddress = this.GetSectionAtVirtualAddress(rva);
			bool flag = sectionAtVirtualAddress == null;
			BinaryStreamReader result;
			if (flag)
			{
				result = null;
			}
			else
			{
				BinaryStreamReader binaryStreamReader = new BinaryStreamReader(this.Stream.value);
				binaryStreamReader.MoveTo(this.ResolveVirtualAddressInSection(rva, sectionAtVirtualAddress));
				result = binaryStreamReader;
			}
			return result;
		}

		// Token: 0x060009B2 RID: 2482 RVA: 0x0002B014 File Offset: 0x00029214
		public TRet GetReaderAt<TItem, TRet>(uint rva, TItem item, Func<TItem, BinaryStreamReader, TRet> read) where TRet : class
		{
			long position = this.Stream.value.Position;
			TRet result;
			try
			{
				BinaryStreamReader readerAt = this.GetReaderAt(rva);
				bool flag = readerAt == null;
				if (flag)
				{
					result = default(TRet);
				}
				else
				{
					result = read(item, readerAt);
				}
			}
			finally
			{
				this.Stream.value.Position = position;
			}
			return result;
		}

		// Token: 0x060009B3 RID: 2483 RVA: 0x0002B084 File Offset: 0x00029284
		public bool HasDebugTables()
		{
			return this.HasTable(Table.Document) || this.HasTable(Table.MethodDebugInformation) || this.HasTable(Table.LocalScope) || this.HasTable(Table.LocalVariable) || this.HasTable(Table.LocalConstant) || this.HasTable(Table.StateMachineMethod) || this.HasTable(Table.CustomDebugInformation);
		}

		// Token: 0x060009B4 RID: 2484 RVA: 0x00005824 File Offset: 0x00003A24
		public void Dispose()
		{
			this.Stream.Dispose();
		}

		// Token: 0x040003C8 RID: 968
		public Disposable<Stream> Stream;

		// Token: 0x040003C9 RID: 969
		public string FileName;

		// Token: 0x040003CA RID: 970
		public ModuleKind Kind;

		// Token: 0x040003CB RID: 971
		public uint Characteristics;

		// Token: 0x040003CC RID: 972
		public string RuntimeVersion;

		// Token: 0x040003CD RID: 973
		public TargetArchitecture Architecture;

		// Token: 0x040003CE RID: 974
		public ModuleCharacteristics DllCharacteristics;

		// Token: 0x040003CF RID: 975
		public ushort LinkerVersion;

		// Token: 0x040003D0 RID: 976
		public ushort SubSystemMajor;

		// Token: 0x040003D1 RID: 977
		public ushort SubSystemMinor;

		// Token: 0x040003D2 RID: 978
		public ImageDebugHeader DebugHeader;

		// Token: 0x040003D3 RID: 979
		public Section[] Sections;

		// Token: 0x040003D4 RID: 980
		public Section MetadataSection;

		// Token: 0x040003D5 RID: 981
		public uint EntryPointToken;

		// Token: 0x040003D6 RID: 982
		public uint Timestamp;

		// Token: 0x040003D7 RID: 983
		public ModuleAttributes Attributes;

		// Token: 0x040003D8 RID: 984
		public DataDirectory Win32Resources;

		// Token: 0x040003D9 RID: 985
		public DataDirectory Debug;

		// Token: 0x040003DA RID: 986
		public DataDirectory Resources;

		// Token: 0x040003DB RID: 987
		public DataDirectory StrongName;

		// Token: 0x040003DC RID: 988
		public StringHeap StringHeap;

		// Token: 0x040003DD RID: 989
		public BlobHeap BlobHeap;

		// Token: 0x040003DE RID: 990
		public UserStringHeap UserStringHeap;

		// Token: 0x040003DF RID: 991
		public GuidHeap GuidHeap;

		// Token: 0x040003E0 RID: 992
		public TableHeap TableHeap;

		// Token: 0x040003E1 RID: 993
		public PdbHeap PdbHeap;

		// Token: 0x040003E2 RID: 994
		private readonly int[] coded_index_sizes = new int[14];

		// Token: 0x040003E3 RID: 995
		private readonly Func<Table, int> counter;
	}
}
